
import java.util.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Date;
import java.util.Map;
import java.util.Vector;
import java.util.Calendar;

/**
 * What if no search result found?????? 
 * should it be handled by datastruc???????
 * @author Theresa
 *
 */

public class logic {

	private DataStruc datastruc;
	      
	public logic() {
		datastruc=new DataStruc();
		readFromFile();
	}

	private String toString(Task x) {
		String val="";
		val+=x.name+'\n';
		val+=x.StartTime.toString()+'\n';
		
		if(x.getClass().getName()=="Event")
			val+=((Event) x).EndTime.toString()+'\n';
		val+=Integer.toString(x.priority)+'\n';
		
		if(x.done)
			val+="Done";
		else
			val+="Not done";
		return val;
	}
	
	/**
	 * this operation create a task object and call add method in datastruc
	 * @param name
	 * @param Starttime
	 * @param done
	 * @param priority
	 * @return
	 */
	 public String add(String name,Date Starttime,int priority){
		Task x=new Task(priority,Starttime,name,false);
		if(datastruc.add(x))
			return "Task added successfully.";
		else
			return "Failed to add task.";
	}
	 /**
	  * this operation create an event object and call the method in datastruc
	  * @param name
	  * @param Starttime
	  * @param Endtime
	  * @param done
	  * @param priority
	  * @return
	  */
	 public String add(String name,Date Starttime,Date Endtime,boolean done,int priority){
		 Task x=new Event(priority,Starttime,Endtime,name,done);
		 if(datastruc.add(x))
			 return "Event added successfully.";
		 else
			 return "Failed to add event.";
	 }
	 /**
	  * This operation searches for tasks/events with a certain name.
	  * @param x
	  * @return Vector containing tasks/events matching field
	  */
	 public Vector<Task> search (String name){
		 return datastruc.search(name);
	 }
	 /**
	  * user decide which type of date to search for?Or we decide for user?
	  * @param type
	  * @param time
	  * @return
	  */
    public Task search(DataStruc.DATE_TYPE type,Date time) {
       return datastruc.search(type, time);
		 
	 }
	 
	 public boolean singleSearchResult(Vector<Task> task){
		 if (task.size()==1)
			 return true;
		 else 
			 return false;
	   }
	 
	 /**
	  * this mark operation will perform a search first
	  * will only continue mark operation when only single task is found
	  * 2 scenarios:
	  * 1.name=null OR
	  * 2.type=null and time=null
	  * @param name:name of the event or task user would like to search for
	           (null if not search by name)
	  * @param type:time type user would like to search for
	  *        (null if not search by time)
	  * @param time
	  *        (null if not search by time)
	  * @return true :when successfully marked
	  */
	 public boolean mark(String name,DataStruc.DATE_TYPE type,Date time){
		 Task tobeMarked;
		 if(time!=null){
			 tobeMarked=search(type,time);
			 datastruc.mark(tobeMarked);
			 return true;
		 }
		 else if(singleSearchResult(search(name))){
			 tobeMarked=search(name).get(0);
			 datastruc.mark(tobeMarked);
			 return true;
		}
		 else 
			 return false;
	 }
	
	 /**
	  * delete by providing information of 1.type of time 2.time to search for the task or event need
	  * to be deleted
	  * @param type:  time type user would like to search from
	  * @param time
	  * @return true when delete successfully
	  */
	 public boolean delete(DataStruc.DATE_TYPE type,Date time){
		 Task tobeDeleted=datastruc.search(type, time);
		 if(tobeDeleted==null)
			 return false;
		 else
		    datastruc.delete(tobeDeleted);
		    return true;
	 }
	 /**
	  * deleted by name
	  * perform a search first, only deleted from datastruc when there is no duplicates
	  * @param name
	  * @return true when deleted successfully
	  */
	 public boolean delete(String name){
		 Vector<Task> tobeDeleted=search(name);
		 if(tobeDeleted.isEmpty())
			 return false;
		 if(tobeDeleted.size()>1)
			 return false;
		 else
			 datastruc.delete(tobeDeleted.get(0));
		     return true;
	 }
	 
	 /**
	  * this operation performs edition of task's name
	  * pass in either task's 1.old name or 2.time type and time  to do a search first
	  * @param name
	           (null if not search by name)
	  * @param type:time type (start or end)
	  *        (null if not search by time)
	  * @param time
	  *        (null if not search by time)
	  * @param new_name
	  * @return true :when successfully edited
	  */
	  public boolean editName(String name,DataStruc.DATE_TYPE type,Date time,String new_name){
		 Task tobeEdited;
		 if(time!=null){
			 tobeEdited=search(type,time);
		     datastruc.edit(tobeEdited, -1, new_name);
		     return true;
		 }
		 else if(singleSearchResult(search(name))){
			  tobeEdited=search(name).get(0);
			  datastruc.edit(tobeEdited, -1, new_name);
			  return true;
		 }
		 else
			 return false;
			 
	 }
	
	  /**
	   * this operation performs edition of task's priority
	   * pass in either 1.task's old name or 2.time type and time to do a search first
	   * @param name
	            (null if not search by name)
	   * @param type
	            (null if not search by time)
	   * @param time
	             (null if not search by time) 
	   * @param new_priority
	   * @return
	   */
	  public boolean editPriority(String name,DataStruc.DATE_TYPE type,Date time,int new_priority){
		  Task tobeEdited;
			 if(time!=null){
				 tobeEdited=search(type,time);
			     datastruc.edit(tobeEdited, new_priority, null);
			     return true;
			 }
			 else if(singleSearchResult(search(name))){
				  tobeEdited=search(name).get(0);
				  datastruc.edit(tobeEdited, new_priority, null);
				  return true;
			 }
			 else
				 return false;
	  }
	  /**
	   * this operation perform edition of a task's start time and end time
	   * pass in either task's name or old start time to do a search first
	   * if single result found perform edition
	   * @param name(task name)
	   * @param time(old start time)
	   * @param new_starttime
	   * @param new_endtime
	   * @return
	   */
	 public boolean editTime(String name,DataStruc.DATE_TYPE type,Date time,Date new_starttime,Date new_endtime){
		 Task tobeEdited;
		 
		 if(time!=null)
			  tobeEdited=search(type,time);
		 else
			  tobeEdited=search(name).get(0);//need to comfirm only one result after search!!!!!!!!!!!!!!!!!!!
		 if(new_endtime==null){ 
			   datastruc.edit(tobeEdited, new_starttime, null, -1, null) ;
		      return true;
		 }
		 else{
			 datastruc.edit(tobeEdited, new_starttime, new_endtime, -1, null);
		     return true;
		 }
			 
	 }
	 /***************read file format**************/
	 /*********************************************
	 taskname priority done starttime (hhmmddmmyyy)
	 eventname priority done starttime endtime 
	 ************************************************/
	/**
	 * read from file and return a vector of strings of objects
	 * @return
	 */
	 public static Vector<String> readFromFile(){
		File file=new File("data.txt");
		Vector<String> data=new Vector<String>();
		try{
			Scanner scanner=new Scanner(file);
			while(scanner.hasNextLine()){
				String line=scanner.nextLine();
	            data.add(line);
			}
			scanner.close();
		}catch (FileNotFoundException e){
			e.printStackTrace();
		}
		return data;
	}
	public String getFirstWord(String input){
		String command = input.trim().split("\\s+")[0];
	    return command;
	}
	public String removeFirstWord(String userInput) {
		return userInput.replace(getFirstWord(userInput), "").trim();
	}
	
	public Date constructDate(String datedata) {
		Calendar temp=new GregorianCalendar();
		String hour=datedata.trim().substring(0,1);
		String min=datedata.trim().substring(2,3);
		String day=datedata.trim().substring(4,5);
		String month=datedata.trim().substring(6,7);
		String year=datedata.trim().substring(8,11);
		int hh=Integer.parseInt(hour);
		int mi=Integer.parseInt(min);
		int dd=Integer.parseInt(day);
		int mm=Integer.parseInt(month);
		int yy=Integer.parseInt(year)-1900;
		temp.set(yy,mm,dd,mi,hh);
		Date date = new Date(temp.getTimeInMillis());
		return date;
	}
	/**
	 * this operation process the Vector<String> reaad from the file
	 * and add to the datastruc one by one.
	 * @param data
	 */
	public void processReadInfo(Vector<String> data){
		String name;
		int priority;
		boolean done;
		Date starttime,endtime;
		for(int i=0;i<data.size();i++){
			name=getFirstWord(data.get(i));
			    removeFirstWord(data.get(i));
			priority=Integer.parseInt(getFirstWord(data.get(i)));
			    removeFirstWord(data.get(i));
			 if(getFirstWord(data.get(i))=="0")
				 done=false;
			 else
				 done=true;
			    removeFirstWord(data.get(i));
			 starttime=constructDate(data.get(i));
			     removeFirstWord(data.get(i));
			 if(!data.get(i).isEmpty()){
				 endtime=constructDate(data.get(i));
				 add(name,starttime,endtime,done,priority);
			 }
			 else
				 add(name,starttime,priority);
		}
		
	}
	
	public String displayToday() {
		Calendar temp=Calendar.getInstance();
		temp.set(Calendar.HOUR, 0);
		temp.set(Calendar.MINUTE, 0);
		temp.set(Calendar.SECOND, 0);
		temp.set(Calendar.MILLISECOND, 0);
		Date from=temp.getTime();
		temp.add(Calendar.DAY_OF_YEAR, 1);
		Date to=temp.getTime();
		Map<Date, Task> map=datastruc.search(DataStruc.DATE_TYPE.start, from, to);
		StringBuilder sb=new StringBuilder();
		
		for (Map.Entry<Date, Task> entry : map.entrySet()) {
			sb.append(toString(entry.getValue()));
			sb.append("\n\n");
		}
		
		int size=sb.length();
		
		if(size>0)
			sb.delete(size-2, size);
		return sb.toString();
	}
}






